/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT,
 * THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package lineage.packet.client;

import java.sql.Timestamp;
import java.util.regex.Matcher;

import lineage.bean.L1IdFactoryPc;
import lineage.config.L1Config;
import lineage.controller.L1AccountController;
import lineage.controller.pc.L1PcController;
import lineage.core.L1GameClient;
import lineage.model.instance.L1PcInstance;
import lineage.packet.L1AbstractPacketClient;
import lineage.packet.server.S_CharCreate;
import lineage.packet.server.S_CharCreateResult;
import lineage.txt.L1BanName;
import lineage.util.DateTimeUtil;

/**
 * 处理客户端封包：请求新建角色.
 * 
 * @version 2014年3月15日下午10:21:33
 * @author jrwz
 */
public final class C_CharCreate extends L1AbstractPacketClient {

    @Override
    public void execute(final L1GameClient client, final byte[] data) {
        try {
            this.init(data);

            final L1PcInstance pc = new L1PcInstance();
            final String name = Matcher.quoteReplacement(readS());
            if (!checkName(client, pc, name)) { // 检查名称是否合法
                return;
            }

            pc.setType(readC());
            pc.setSex(readC());
            pc.setStr(readC());
            pc.setDex(readC());
            pc.setCon(readC());
            pc.setWis(readC());
            pc.setCha(readC());
            pc.setInt(readC());

            if (!checkCharCount(client)) { // 检查能否创建新角色
                return;
            }
            if (!checkStatus(client, pc)) { // 检查该角色的数据(能力值等等)
                return;
            }

            client.sendPacket(new S_CharCreateResult(S_CharCreateResult.REASON_OK));
            initNewChar(client, pc); // 初始化角色数据
        } catch (final Exception e) {
        } finally {
            this.close();
        }
    }

    /**
     * 检查名称是否合法.
     * 
     * @param client
     *            - 客户端对象
     * @param pc
     *            - 角色
     * @param name
     *            - 名称
     * @return 如果合法则返回true
     */
    private boolean checkName(final L1GameClient client, final L1PcInstance pc, String name) {
        name = name.replaceAll("\\s", "");
        name = name.replaceAll("　", "");
        if (name.length() < 1) {
            client.sendPacket(new S_CharCreateResult(S_CharCreateResult.REASON_INVALID_NAME));
            return false;
        }

        final boolean isBan = L1BanName.getInstance().isBanName(name);
        if (isBan) { // 是否被禁止使用
            client.sendPacket(new S_CharCreateResult(S_CharCreateResult.REASON_INVALID_NAME));
            return false;
        }

        final boolean isName = L1PcController.isName(name);
        if (isName) { // 是否已经使用
            client.sendPacket(new S_CharCreateResult(S_CharCreateResult.REASON_ALREADY_EXISTS));
            return false;
        }

        pc.setName(name);
        return true;
    }

    /**
     * 检查能否创建新角色.
     * 
     * @param client
     *            - 客户端对象
     * @return 如果可以创建则返回true
     */
    private boolean checkCharCount(final L1GameClient client) {
        boolean flag = true;
        final String accountName = client.getAccountName();
        final int count = L1AccountController.getInstance().getCharCount(accountName);
        if (count >= L1Config.CHAR_MAX_COUNT) {
            client.sendPacket(new S_CharCreateResult(S_CharCreateResult.REASON_WRONG_AMOUNT));
            flag = false;
        }
        return flag;
    }

    /**
     * 检查该角色的数据(能力值等等).
     * 
     * @param client
     *            - 客户端对象
     * @param pc
     *            - 角色
     * @return 如果没问题则返回true
     */
    private boolean checkStatus(final L1GameClient client, final L1PcInstance pc) {
        boolean isError = false;
        final int originalStr = L1PcController.getOriginalStr(pc);
        final int originalDex = L1PcController.getOriginalDex(pc);
        final int originalCon = L1PcController.getOriginalCon(pc);
        final int originalWis = L1PcController.getOriginalWis(pc);
        final int originalInt = L1PcController.getOriginalInt(pc);
        final int originalCha = L1PcController.getOriginalCha(pc);
        final int originalCount = L1PcController.getOriginalCount(pc);

        if (((pc.getStr() < originalStr) //
                || (pc.getDex() < originalDex) //
                || (pc.getCon() < originalCon) //
                || (pc.getWis() < originalWis) //
                || (pc.getInt() < originalInt) //
        || (pc.getCha() < originalCha)) //
                || ((pc.getStr() > originalStr + originalCount) //
                        || (pc.getDex() > originalDex + originalCount) //
                        || (pc.getCon() > originalCon + originalCount) //
                        || (pc.getWis() > originalWis + originalCount) //
                        || (pc.getInt() > originalInt + originalCount) //
                || (pc.getCha() > originalCha + originalCount)) //
        ) {
            isError = true;
        }

        final int count = pc.getStr() + pc.getDex() + pc.getCon() + pc.getWis() + pc.getInt() + pc.getCha();
        if ((count != 75) || isError) {
            client.sendPacket(new S_CharCreateResult(S_CharCreateResult.REASON_WRONG_AMOUNT));
            return false;
        }
        return true;
    }

    /**
     * 初始化角色数据.
     * 
     * @param client
     *            - 客户端对象
     * @param pc
     *            - 角色
     */
    private void initNewChar(final L1GameClient client, final L1PcInstance pc) {
        pc.setSpareType(pc.getType());
        pc.setAccountName(client.getAccountName());
        pc.setId(L1IdFactoryPc.getInstance().nextId());
        pc.setClassId(L1PcController.getClassId(pc));
        final int[] loc = L1PcController.getLocation(pc);
        pc.setX(loc[0]);
        pc.setY(loc[1]);
        pc.setMapId(loc[2]);
        pc.setHeading(6);
        pc.setLawful(0);

        final int hp = L1PcController.getOriginalHp(pc);
        pc.setHp(hp);
        pc.setMaxHP(hp);

        final int mp = L1PcController.getOriginalMp(pc);
        pc.setMp(mp);
        pc.setMaxMP(mp);

        pc.setTitle("");
        pc.setClanId(0);
        pc.setClanName("");
        pc.setClanRank(0);
        pc.setFood(40);
        pc.setAccessLevel(0);
        pc.setExp(0);
        pc.setAction(0);
        pc.setStatus(4);
        final Timestamp ts = DateTimeUtil.getTimestampMillis();
        pc.setCreateTime(ts);
        pc.setDeleteTime(new Timestamp(0));
        pc.setOriginalStr(pc.getStr());
        pc.setOriginalDex(pc.getDex());
        pc.setOriginalCon(pc.getCon());
        pc.setOriginalWis(pc.getWis());
        pc.setOriginalCha(pc.getCha());
        pc.setOriginalInt(pc.getInt());
        pc.refresh(); // 初始化各属性

        L1PcController.addCharacters(client, pc);
        client.sendPacket(new S_CharCreate(pc));
    }
}
